package com.vikstrom.LTimePictureViewer;

import com.vikstrom.LTimePictureViewer.util.SystemUiHider;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Random;
import java.util.TreeMap;

/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 *
 * @see SystemUiHider
 */
public class DefaultScreenActivity extends Activity {
    /**
     * If set, will toggle the system UI visibility upon interaction. Otherwise,
     * will show the system UI visibility upon interaction.
     */
    private static final boolean TOGGLE_ON_CLICK = true;

    /**
     * The flags to pass to {@link SystemUiHider#getInstance}.
     */
    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;

    /**
     * The instance of the {@link SystemUiHider} for this activity.
     */
    private SystemUiHider mSystemUiHider;

    private TextView dayTextView;
    private TextView dayView;
    private TextView dateView;
    private TextView dayTextImageName;
    private TextView dayTextImageDescription;
    private TextView birthdayView;

    private int monthDay;
    private int month;
    private int weekday;
    private int hour;
    private LinkedList<Birthday> birthdays;
    private int pictureChangeCounter;
    private int pictureChangeCounterMax;

    private boolean debugMode = false;
    private StorageHelper storageHelper;
    private ArrayList<LPicture> pictures;

    private RefreshHandler mRedrawHandler;

    class RefreshHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            DefaultScreenActivity.this.update();
        }

        public void sleep(long delayMillis) {
            this.removeMessages(0);
            sendMessageDelayed(obtainMessage(0), delayMillis);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_default_screen);

        final View contentView = findViewById(R.id.fullscreen_content);

        debugMode = false;

        // helper class to check storage
        storageHelper = new StorageHelper();
        pictures = storageHelper.getPictures("bilder");
        pictureChangeCounterMax = Integer.valueOf(getResources().getString(R.string.pictureChangeCounter));
        pictureChangeCounter = -1;

        mRedrawHandler = new RefreshHandler();

        dayTextView = (TextView) findViewById(R.id.daytextLabel);
        dayView = (TextView) findViewById(R.id.dayLabel);
        dateView = (TextView) findViewById(R.id.dateLabel);
        birthdayView = (TextView) findViewById(R.id.birthdayLabel);
        dayTextImageName = (TextView) findViewById(R.id.dayTextImageName);
        dayTextImageDescription = (TextView) findViewById(R.id.dayTextImageDescription);


        birthdays = initBirthdays(new GregorianCalendar());
        // Set up an instance of SystemUiHider to control the system UI for
        // this activity.
        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
        mSystemUiHider.setup();
        mSystemUiHider
                .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {


                    @Override
                    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
                    public void onVisibilityChange(boolean visible) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
                            // If the ViewPropertyAnimator API is available
                            // (Honeycomb MR2 and later), use it to animate the
                            // in-layout UI controls at the bottom of the
                            // screen.
                            /**
                            if (mControlsHeight == 0) {
                                mControlsHeight = controlsView.getHeight();
                            }
                            if (mShortAnimTime == 0) {
                                mShortAnimTime = getResources().getInteger(
                                        android.R.integer.config_shortAnimTime);
                            }
                            controlsView.animate()
                                    .translationY(visible ? 0 : mControlsHeight)
                                    .setDuration(mShortAnimTime);
                             */
                        } else {
                            // If the ViewPropertyAnimator APIs aren't
                            // available, simply show or hide the in-layout UI
                            // controls.
                            //controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
                        }
                    }
                });


        // Set up the user interaction to manually show or hide the system UI.
        contentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mSystemUiHider.toggle();
                } else {
                    mSystemUiHider.show();
                }
            }
        });

        // Upon interacting with UI controls, delay any scheduled hide()
        // operations to prevent the jarring behavior of controls going away
        // while interacting with the UI.
        //findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);

        if (debugMode) {
            monthDay = 1;
            month = Calendar.JANUARY;
            weekday = 1;
            hour = 0;
        }

        update();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100);
    }


    Handler mHideHandler = new Handler();
    Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            mSystemUiHider.hide();
        }
    };

    /**
     * Schedules a call to hide() in [delay] milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

    private void update() {
        Calendar calendar;
        if (debugMode) {
            if (++monthDay > 31) monthDay = 1;
            if (++month > 11) month = Calendar.JANUARY;
            if (++weekday > 7) weekday = 1;
            if (++hour > 23) hour = 0;
            int year = 2013;
            calendar = new GregorianCalendar(year, month, monthDay);
        } else {
            calendar = new GregorianCalendar();
            monthDay = calendar.get(Calendar.DAY_OF_MONTH);
            month = calendar.get(Calendar.MONTH);
            weekday = calendar.get(Calendar.DAY_OF_WEEK);
            hour = calendar.get(Calendar.HOUR_OF_DAY);
        }

        setDayText(hour);
        setWeekday(weekday);
        setMonthDay(month, monthDay);
        setDayImage(month, hour);
        setBirthdayText(calendar);

        long mMoveDelay = 1000;
        mRedrawHandler.sleep(mMoveDelay);
    }

    private void setBirthdayText(Calendar nowCal) {
        Resources res = getResources();
        TreeMap<Calendar, Birthday> showableBirthdays = new TreeMap<Calendar, Birthday>();
        String bText = res.getString(R.string.defaultbirthday);

        if (!birthdays.isEmpty()) {
            ListIterator<Birthday> birthdayListIterator = birthdays.listIterator();

            while (birthdayListIterator.hasNext())
            {
                Birthday personBirthday = birthdayListIterator.next();
                Calendar personCal = personBirthday.getBirthday();
                Calendar thisYearCal = new GregorianCalendar(nowCal.get(Calendar.YEAR), personCal.get(Calendar.MONTH), personCal.get(Calendar.DAY_OF_MONTH));

                long daysBetween = personBirthday.getNumDaysToBirthday(nowCal);
                if (daysBetween >= 0) {
                    int maxDaysBetween = Integer.valueOf(res.getString(R.string.showbirthday));
                    if (daysBetween <= maxDaysBetween) {
                        showableBirthdays.put(thisYearCal, personBirthday);
                    }
                }
            }

            if (!showableBirthdays.isEmpty()) {
                bText = "";
                for(TreeMap.Entry<Calendar, Birthday> entry : showableBirthdays.entrySet()) {
                    Birthday personBirthday = entry.getValue();

                    String addText;

                    if (personBirthday.getNumDaysToBirthday(nowCal) == 0) {
                        addText = personBirthday.getName() + " fyller idag " + String.valueOf(personBirthday.getAge(nowCal)) + " år";
                    } else {
                        Calendar birthday = personBirthday.getBirthday();
                        addText = birthday.get(Calendar.DAY_OF_MONTH) + "."+
                                (birthday.get(Calendar.MONTH)+1)+" "+
                                personBirthday.getName() + " " +
                                String.valueOf(personBirthday.getAge(nowCal)) + " år - "+
                                personBirthday.getNumDaysToBirthday(nowCal) + " dagar";
                    }

                    if (bText.length() == 0) {
                        bText = addText;
                    } else {
                        bText += "\n" + addText;
                    }
                }
            }
        }

        birthdayView.setText(bText);
    }

    private void setDayText(int hour) {
        if (hour < 6) {
            dayTextView.setText(R.string.nighttime);
        } else if (hour < 10) {
            dayTextView.setText(R.string.morningtime);
        } else if (hour < 18) {
            dayTextView.setText(R.string.daytime);
        } else if (hour < 22) {
            dayTextView.setText(R.string.eveningtime);
        } else {
            dayTextView.setText(R.string.nighttime);
        }
    }

    private void setWeekday(int weekday) {
        switch (weekday) {
            case Calendar.SUNDAY:
                dayView.setText(R.string.sunday);
                break;
            case Calendar.MONDAY:
                dayView.setText(R.string.monday);
                break;
            case Calendar.TUESDAY:
                dayView.setText(R.string.tuesday);
                break;
            case Calendar.WEDNESDAY:
                dayView.setText(R.string.wednesday);
                break;
            case Calendar.THURSDAY:
                dayView.setText(R.string.thursday);
                break;
            case Calendar.FRIDAY:
                dayView.setText(R.string.friday);
                break;
            case Calendar.SATURDAY:
                dayView.setText(R.string.saturday);
                break;
            default:
                dayView.setText(R.string.unknownday);
                break;
        }
    }

    private void setMonthDay(int month, int monthday) {
        String tempString;

        switch (month) {
            case Calendar.JANUARY:
                tempString = String.valueOf(monthday) + " " +  getString(R.string.january);
                dateView.setText(tempString);
                break;
            case Calendar.FEBRUARY:
                tempString = String.valueOf(monthday) + " " + getString(R.string.february);
                dateView.setText(tempString);
                break;
            case Calendar.MARCH:
                tempString = String.valueOf(monthday) + " " + getString(R.string.march);
                dateView.setText(tempString);
                break;
            case Calendar.APRIL:
                tempString = String.valueOf(monthday) + " " + getString(R.string.april);
                dateView.setText(tempString);
                break;
            case Calendar.MAY:
                tempString = String.valueOf(monthday) + " " + getString(R.string.may);
                dateView.setText(tempString);
                break;
            case Calendar.JUNE:
                tempString = String.valueOf(monthday) + " " + getString(R.string.june);
                dateView.setText(tempString);
                break;
            case Calendar.JULY:
                tempString = String.valueOf(monthday) + " " + getString(R.string.july);
                dateView.setText(tempString);
                break;
            case Calendar.AUGUST:
                tempString = String.valueOf(monthday) + " " + getString(R.string.august);
                dateView.setText(tempString);
                break;
            case Calendar.SEPTEMBER:
                tempString = String.valueOf(monthday) + " " + getString(R.string.september);
                dateView.setText(tempString);
                break;
            case Calendar.OCTOBER:
                tempString = String.valueOf(monthday) + " " + getString(R.string.october);
                dateView.setText(tempString);
                break;
            case Calendar.NOVEMBER:
                tempString = String.valueOf(monthday) + " " + getString(R.string.november);
                dateView.setText(tempString);
                break;
            case Calendar.DECEMBER:
                tempString = String.valueOf(monthday) + " " + getString(R.string.december);
                dateView.setText(tempString);
                break;

            default:
                dateView.setText(R.string.unknownmonth);
                break;
        }
    }

    private void setDayImage(int month, int hour) {
        if (!pictures.isEmpty()) {
            // use pictures
            setDayImageFromPicture();
        } else {
            // use old system with internal resources
            String monthText;
            String hourText;
            switch (month) {
                case 3:
                case 4:
                    monthText = "spring";
                    break;
                case 10:
                case 11:
                case 0:
                case 1:
                case 2:
                    monthText = "winter";
                    break;
                case 5:
                case 6:
                case 7:
                    monthText = "summer";
                    break;
                default:
                    monthText = "autumn";
                    break;
            }
            switch (hour) {
                case 6:
                case 7:
                case 8:
                case 9:
                    hourText = "morning";
                    break;
                case 10:
                case 11:
                case 12:
                case 13:
                case 14:
                case 15:
                case 16:
                case 17:
                    hourText = "day";
                    break;
                case 18:
                case 19:
                case 20:
                case 21:
                    hourText = "evening";
                    break;

                default:
                    hourText = "night";
                    break;
            }
            String imageName = monthText + "_" + hourText;
            int imageId;
            imageId = getResources().getIdentifier(imageName, "drawable", "com.vikstrom.LTimePictureViewer");
            if (imageId != 0)
            {
                ImageView dayTextImage = (ImageView) findViewById(R.id.dayTextImage);
                dayTextImage.setImageResource(imageId);
            }
        }
    }

    private void setDayImageFromPicture() {
        pictureChangeCounter++;
        if ((pictureChangeCounter > pictureChangeCounterMax)) {
            pictureChangeCounter = 1;
        }
        if (pictureChangeCounter == 1) {
            // get random picture from list
            Random random = new Random();
            int n = random.nextInt(pictures.size());
            LPicture randomImage = pictures.get(n);

            //Log.d("setDayImageFromPicture", randomImage.getName());

            ImageView dayTextImage = (ImageView) findViewById(R.id.dayTextImage);
            Bitmap pictureBitmap = randomImage.decodeSampledBitmap(dayTextImage.getWidth(), dayTextImage.getHeight());

            if (pictureBitmap != null)
            {
                dayTextImage.setImageBitmap(pictureBitmap);
                dayTextImageName.setText(randomImage.getName());
                dayTextImageDescription.setText(randomImage.getDescription());
            }
            pictureBitmap = null;
        }
    }

    private LinkedList<Birthday> initBirthdays(Calendar nowCal) {
        LinkedList<Birthday> birthdayList = new LinkedList<Birthday>();

        Resources res = getResources();
        String[] birthdays = res.getStringArray(R.array.birthday);

        if (birthdays.length > 0) {
            for (String birthday : birthdays) {
                String[] birthdaypair = birthday.split(";");
                if (birthdaypair.length > 1) {
                    //Log.d("Added birthday", birthdaypair[1] + ":" + birthdaypair[0]);

                    String bDay = birthdaypair[0];

                    int d = Integer.parseInt(bDay.substring(0, 2));
                    int m = Integer.parseInt(bDay.substring(2, 4)) - 1;
                    int y = Integer.parseInt(bDay.substring(4));

                    Calendar personBirthday = new GregorianCalendar(y, m, d, 0, 0, 0);

                    Birthday newBirthday = new Birthday(birthdaypair[1], personBirthday, nowCal);

                    birthdayList.add(newBirthday);
                }
            }
        }

        return birthdayList;
    }
}
